# -*- coding: utf-8 -*-
#
# Author:: Jonny
# Date:: 2018/11/29
import configparser
import getpass
import os
import platform
import re
import socket
import sys
import logging
from logging import handlers
from pathlib import Path

log_conf_basic = {
    # "filename": "install.log",
    # "mode": "w",
    "format": '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
    "datefmt": '%Y-%m-%d %H:%M:%S',
    "level": logging.INFO,
}

log_conf_handler = {
    "filename": "install.log",
    "mode": "w",
    "encoding": "utf-8"
}

handlers_list = []
handler = logging.StreamHandler()
handlers_list.append(handler)
handler = handlers.RotatingFileHandler(**log_conf_handler)
handlers_list.append(handler)

logging.basicConfig(**log_conf_basic, handlers=handlers_list)


def get_user_python_path():
    _host_name = socket.gethostname()
    _user_name = getpass.getuser()
    _UserName_win = "%s\\\\%s" % (_host_name, _user_name)
    res = os.popen('''wmic ENVIRONMENT where "name='PYTHONPATH' and username='%s'"''' % _UserName_win)
    res = res.read().split('  ')
    res_valid = []
    for i in res:
        if i != '':
            res_valid.append(i)
    return res_valid[-2]


def update_bat_script(filename, cmd):
    f = open("bat\\raw.bat", "r+", encoding="ANSI")
    content = f.read()
    f.close()
    f = open("bat\\%s" % filename, "w", encoding="ANSI")
    # f.write(content.replace("$COMMANDS", 'cacls "%s" /t /e /g users:f' % PYTHON_PATH))
    f.write(content.replace("$COMMANDS", '%s' % cmd))
    f.close()


def get_admin_privilege_status(path):
    res = os.popen('cacls "%s"' % path)
    res = res.read()
    res_no_space = res.replace(" ", "")
    res_list = res_no_space.split("\n")

    pattern = re.compile(r'.*BUILTIN\\Users.*F')
    has_admin_pri = False
    for item in res_list:
        if pattern.match(item):
            print(item)
            has_admin_pri = True
    return has_admin_pri


def is_exist_python_path():
    '''Windows环境使用：判断*用户*变量中是否存在"PYTHONPATH"环境变量'''
    _host_name = socket.gethostname()
    _user_name = getpass.getuser()
    _UserName_win = "%s\\\\%s" % (_host_name, _user_name)
    res = os.popen('''wmic ENVIRONMENT where "name='PYTHONPATH' and username='%s'"''' % _UserName_win)
    res = res.read()
    if "PYTHONPATH" in res.upper():
        return True
    else:
        return False
    # 使用wmic方式查询更准确
    # 使用wmic方式 + user_name_win 才能查出用户变量，用os.environ不行
    # for key in os.environ:
    #     if 'PATH' == key:
    #         return True
    # return False


def set_python_path(_project_path):
    _OS_NAME = platform.system()
    if _OS_NAME == "Windows":
        # todo 需要设置环境变量或注销后生效~
        _is_exist_python_path = is_exist_python_path()
        _host_name = socket.gethostname()
        _user_name = getpass.getuser()
        _UserName_win = "%s\\\\%s" % (_host_name, _user_name)
        if _is_exist_python_path == True:
            _user_python_path = get_user_python_path()
            if _project_path not in _user_python_path:
                # 不好获取原先用户变量，使用所有代替原先，会有一些重复
                cmd_set_path = '''wmic ENVIRONMENT where "name='PYTHONPATH' and username='%s'" set VariableValue="%s;%s" ''' % (
                    _UserName_win, _project_path, _user_python_path)
                logging.info(cmd_set_path)
                os.system(cmd_set_path)
                # update_bat_script("set_path.bat", cmd_set_path)
                # os.system("bat\\set_path.bat")
            else:
                logging.info('project path already in PYTHONPATH.')
        else:
            cmd_add_path = 'wmic ENVIRONMENT create name="PYTHONPATH",username="%s",VariableValue="%s"' % (
                _UserName_win, _project_path)
            logging.info(cmd_add_path)
            os.system(cmd_add_path)
            # update_bat_script("add_path.bat", cmd_add_path)
            # os.system("bat\\add_path.bat")
    elif _OS_NAME == 'Mac' or _OS_NAME == 'Darwin' or _OS_NAME == 'Linux':
        user_home = os.environ['HOME']
        profile_path = '%s/.bash_profile' % user_home
        f = open(profile_path, 'r+', encoding='utf-8')
        if _project_path in f.read():
            logging.info('Project path already in PYTHONPATH.')
        else:
            f.write('export PYTHONPATH="%s:${PYTHONPATH}"' % _project_path)
        f.close()
        os.system('source %s' % profile_path)
    else:
        pass


def get_admin_privilege(_path):
    logging.info('Get admin privilege.')
    OS_NAME = platform.system()
    if OS_NAME == "Windows":
        if get_admin_privilege_status(_path) == False:
            update_bat_script("set_privilege.bat", 'cacls "%s" /t /e /g users:f' % _path)
            os.system("bat\\set_privilege.bat")
    else:
        pass


def get_python_path():
    '''Windows环境加权限用'''
    pattern = re.compile(r"^.*[0-9]$")
    for item in sys.path:
        if "Python" in item and pattern.match(item):
            python_path = item
            break
    return python_path


def get_project_path():
    '''兼容Win、Mac、Linux'''
    project_path = sys.path[0]
    return project_path


# install集成到一个文件避免import问题
# 1 PROJECT_PATH并写入配置文件
# 1-1 若没有common.conf则创建
# todo 递归创建文件夹及文件
conf_dir = 'config'
conf_path = 'config/common.conf'
if os.path.exists(conf_dir):
    file = Path(conf_dir)
    if file.is_dir():
        pass
    else:
        os.mkdir('config')
else:
    os.mkdir('config')

if os.path.exists(conf_path):
    pass
else:
    f = open(conf_path, 'w', encoding='utf-8')
    f.write('[basic-info]')
    f.close()

# 1-2 获取PROJECT_PATH并写入配置文件
logging.info('Write project path.')
project_path = get_project_path()
if os.path.exists(conf_path):
    cf = configparser.ConfigParser()
    cf.read(conf_path, encoding='utf-8')
    cf.set("basic-info", "project_path", project_path)
else:
    logging.error('Config file is not exist.')
    exit(0)

# 2 将PROJECT_PATH添加到PYTHONPATH-重新登录Shell生效
logging.info('Set project path.')
set_python_path(project_path)

# 3 安装pipenv及依赖
# 3-1 若为Windows先获取python安装目录权限
python_root_path = get_python_path()
get_admin_privilege(python_root_path)
# 3-2 安装
logging.info('Install pipenv and libs.')
os.system("pip3 install pipenv")
os.system("pipenv install")

# 4 获取VIRTUALENV_PATH并记录入配置文件
logging.info('Write virtualenv path.')
virtualenv_path = os.popen("pipenv --venv").read().strip()
cf.set("basic-info", "virtualenv_path", virtualenv_path)
with open(conf_path, "w+") as f:
    cf.write(f)
f.close()
logging.warning('环境变量在重新登录Shell后生效，Windows系统在注销或重启后生效~')
if platform.system() == 'Windows':
    os.system("pause")
